package common.utils.traingenerate;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import common.utils.GetAllFilesOfDir;

/**
 * Se encarga de generar los archivos para entrenar la red y los utilizados para probar la misma
 * en base a los archivos con los coeficientes de mfcc obtenidos.
 * @author Martin
 *
 */
public class GenerarEntradasMescladas {

	private String dirCoefSeparados = "D:/WAVS_TO_COEF/Prueba10Set1/individuales/";
	private String dirArchGenerados = "d:/WAVS_TO_COEF/Prueba10Set1/generados/";
	
	private static final Logger  logger  = Logger.getLogger(GenerarEntradasMescladas.class);

	
	public GenerarEntradasMescladas(){
		
	}
	
	
	/**
	 * Genera los archivos pero sin hacer la segunda normalizacion, 
	 * solo toma un coeficiente de los 13 que saca 
	 * @param args
	 */
	public void procesar(Integer cantOfCoef) {
		
		GetAllFilesOfDir g=new GetAllFilesOfDir();
		
		//lista que contendra todos los directorios de los cuales obtuve parametros, y tengo que procesar
		List<File> directorios=new ArrayList<File>();
		
		directorios.addAll(
				g.getListNameOfDirInDir( 
						dirCoefSeparados,
						new FilenameFilter() {
							public boolean accept(File dir, String name){
								return (name.endsWith("Coef"));	
							}
						}
				)
		);
		
		logger.info("Obtenemos datos de los siguientes directorios de coeficientes: ");
		for (int i = 0; i < directorios.size(); i++) {
			logger.info(directorios.get(i).getAbsolutePath());
		}
		
		File dirArchGen = new File(dirArchGenerados);
		if (!dirArchGen.exists()){
			dirArchGen.mkdirs();
		}
		
		try {
		
			logger.info("**************************************************************************************");
			for (Integer i=1;i<=cantOfCoef;i++){
				final Integer h=i;
				String dirCoef=dirArchGenerados+"coef"+i;
				
				logger.info("CREAMOS LOS ARCHIVOS PARA EL COEFICIENTE "+i);
				
				File dirCreated = new File(dirCoef);
				if (!dirCreated.exists()){
					dirCreated.mkdir();
				}
	
				//creo los archivos que usa la red
				File fileParaEntrenar=new File(dirCoef+"/paraentrenar.txt");
				if (!fileParaEntrenar.exists()){ fileParaEntrenar.createNewFile(); }
				File fileParaEntrenarResultados=new File(dirCoef+"/paraentrenarresultados.txt");
				if (!fileParaEntrenarResultados.exists()){ fileParaEntrenarResultados.createNewFile(); } 
				File fileParaProbar=new File(dirCoef+"/paraprobar.txt");
				if (!fileParaProbar.exists()){ fileParaProbar.createNewFile(); } 
				File fileParaProbarResultados=new File(dirCoef+"/paraprobarresultados.txt");
				if (!fileParaProbarResultados.exists()){ fileParaProbarResultados.createNewFile(); } 
				File fileErrores=new File(dirCoef+"/errores.txt");
				if (!fileErrores.exists()){ fileErrores.createNewFile(); } 
		
				FileOutputStream writerParaEntrenar = new FileOutputStream(fileParaEntrenar);
				FileOutputStream writerParaEntrenarResultados = new FileOutputStream(fileParaEntrenarResultados);
				FileOutputStream writerParaProbar = new FileOutputStream(fileParaProbar);
				FileOutputStream writerParaProbarResultados = new FileOutputStream(fileParaProbarResultados);
					
				ArrayList<FileInfo> archivosCoeficientesActual = new ArrayList<FileInfo>();
			
				int numLineaMasGrande = 0;
				
				//recorro los directorios de las palabras que quiero agregar en los archivos
				for (File dir:directorios){
					
					//obtengo el nombre de la palabra al cual pertenece el directorio
					String palabra = dir.getName().substring(0,dir.getName().length()-4);
					String palabraResult = getResult(palabra);
					
					//obtengo el archivo del coeficiente que estoy procesando, dentro del directorio actual
					File archivoCoef=g.getNameOfFilesInDir(
										dir,
										new FilenameFilter() {
											public boolean accept(File dir, String name){
												return (name.contains("coef"+h.toString()+".txt"));	
											}
										}
								);
					
					
					FileReader fr = new FileReader(archivoCoef);
					BufferedReader bf = new BufferedReader(fr);
	                    
					String sCadena=null;
					
					List<String> registros = new ArrayList<String>(); 
	    
					logger.info("Proceso el archivo: "+ archivoCoef.getAbsolutePath());
	                    
	                while ((sCadena = bf.readLine())!=null) {

	                    registros.add(sCadena);
	                    
	                }	                            

					archivosCoeficientesActual.add(new FileInfo(registros, palabra, palabraResult));
					
					if (registros.size()>numLineaMasGrande)
					    numLineaMasGrande = registros.size();

				}	
				

				
				for (int pp=0; pp<50; pp++) {
                    
				    Iterator<FileInfo> it = archivosCoeficientesActual.iterator();
				    
				    while (it.hasNext()) {
                        
				        FileInfo fileInfo = it.next();
				        
		                //es la cantidad de cada palabra que voy a poner por iteracion cuando voy armando el archivo
		                //por defecto va 1, es un registro por palabra por iteracion
		                int cantRepeticiones = fileInfo.getRepeticionesXPalabra();

				        int numberOfLines = fileInfo.getRegistrosTotales();
				        
//				        System.out.println("procesando archivo perteneciente a la palabra "+fileInfo.getPalabra());
	     				       
				        int a=0;
				        while ( a < cantRepeticiones) {
                            
				            int indiceReal=fileInfo.getIndice();
				            
    	                    //para entrenar
    	                    if (indiceReal <= numberOfLines - 10 ){
    	                            
    	                        System.out.println("para entrenar "+fileInfo.getPalabra());
    	                        writerParaEntrenar.write(fileInfo.getNextWord().getBytes());
    	                        writerParaEntrenar.write("\n".getBytes());
    	                        
    	                        writerParaEntrenarResultados.write(fileInfo.getResultado().getBytes());
    	                        writerParaEntrenarResultados.write("\n".getBytes());
    	    
    	                    }
    	                    //para probar
    	                    if (indiceReal > numberOfLines - 10 && indiceReal<numberOfLines){
    	                        
    	                        System.out.println("para probar "+fileInfo.getPalabra());
    	                        writerParaProbar.write(fileInfo.getNextWord().getBytes());
    	                        writerParaProbar.write("\n".getBytes());                
    	            
    	                        writerParaProbarResultados.write(fileInfo.getResultado().getBytes());
    	                        writerParaProbarResultados.write("\n".getBytes());              
    	                            
    	                    }
	                    
    	                    a++;
 				        }
				   }
			   
				}
				
				
				//cierro los archivos
				writerParaEntrenar.flush();
				writerParaEntrenar.close();
				writerParaEntrenarResultados.flush();
				writerParaEntrenarResultados.close();
				writerParaProbar.flush();
				writerParaProbar.close();
				writerParaProbarResultados.flush();
				writerParaProbarResultados.close();
				
				logger.info("Se creo el archivo: "+ fileParaEntrenar.getAbsolutePath()+" para el coeficiente actual.");
				logger.info("Se creo el archivo: "+ fileParaEntrenarResultados.getAbsolutePath()+" para el coeficiente actual.");
				logger.info("Se creo el archivo: "+ fileParaProbar.getAbsolutePath()+" para el coeficiente actual.");
				logger.info("Se creo el archivo: "+ fileParaProbarResultados.getAbsolutePath()+" para el coeficiente actual.");
				logger.info("Se creo el archivo: "+ fileErrores.getAbsolutePath()+" para el coeficiente actual.");
				logger.info("**************************************************************************************");
				
			}
		}catch (Exception e) {
			// TODO: handle exception
		}
		
		
	}


	/**
	 * Le paso el coeficiente y me dice el resultado esperado
	 * @return
	 */
	private String getResult(String palabra){

//		if (palabra.startsWith("luces")){
	    if (palabra.startsWith("luz")){
			return "0.0;0.0;1.0";
		}
//		if (palabra.startsWith("tv")){
		if (palabra.startsWith("video")){    
			return "0.0;1.0;1.0";
		}
		if (palabra.startsWith("radio")){
			return "0.0;1.0;0.0";
		}
//		if (palabra.startsWith("puerta")){
		if (palabra.startsWith("trabar")){
			return "1.0;0.0;1.0";
		}
		if (palabra.startsWith("persiana")){
			return "1.0;1.0;1.0";
		}
		
		return "0.0;0.0;0.0";
		
	}
	
    /**
     * Le paso el coeficiente y me dice el resultado esperado
     * @return
     */
    private int getRepeticionesByWord(String palabra){

        if (palabra.startsWith("otros")){
            return 3;
        }
        return 2;
        
    }
    

	
	public class FileInfo{
	    //contiene los registros del archivo
	    private List<String> archivo;
	    private String palabra;
	    private String resultado;
	    
	    private int indice = 0;
	    private int registrosTotales = 0;
	    private int repeticionesXPalabra = 0;
	    
	    
	    public FileInfo(List<String> archivo, String palabra, String resultado ){
	        this.archivo = archivo;
	        this.palabra = palabra;
	        this.resultado = resultado;
	        this.registrosTotales = archivo.size();
	        this.repeticionesXPalabra = getRepeticionesByWord(palabra);
	    }

	    public String getNextWord(){
	        if (indice<registrosTotales)	        
	            return archivo.get(indice++);
	        
	        return "";
	    }

        public String getPalabra() {
            return palabra;
        }

        public void setPalabra(String palabra) {
            this.palabra = palabra;
        }

        public String getResultado() {
            return resultado;
        }

        public void setResultado(String resultado) {
            this.resultado = resultado;
        }

        public int getIndice() {
            return indice;
        }

        public int getRegistrosTotales() {
            return registrosTotales;
        }

        public int getRepeticionesXPalabra() {
            return repeticionesXPalabra;
        }
      	    
	}
}
